package controller;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import model.Contact;
import model.Contacts;
import view.FileWindow;
import view.MainWindow;
import view.ViewWindowControlerInterface;

public final class Controller implements ControllerInterface, ViewWindowControlerInterface {

    private static final int SLEEPFORDEBUG = 50;

    private MainWindow mainWindow;
    private Contacts contacts;
    private Controller controller;

    public Controller(MainWindow mainWindow, Contacts contacts) {
        super();
        this.mainWindow = mainWindow;
        this.contacts = contacts;
        this.mainWindow.setController(this);
        this.controller = this;

        List<Contact> contactsList = new ArrayList<Contact>();
        Map<String, Contact> contactsMap = contacts.getAllContacts();

        Iterator<Entry<String, Contact>> it = contactsMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, Contact> pairs = (Map.Entry<String, Contact>) it.next();
            contactsList.add(pairs.getValue());
            it.remove();
        }

        this.mainWindow.fillTable(contactsList);
    }

    @Override
    public void addContact(String fName, String lName, String hAddress,
            String cAddress, List<String> pPhones, List<String> cPhones,
            String homePage, List<String> emails, String photo,
            Map<String, String> others, List<String> groups, Date insertDate) {
        this.contacts.addContact(new Contact(fName, lName, hAddress, cAddress,
                pPhones, cPhones, homePage, emails, photo, others, groups,
                insertDate));

    }

    @Override
    public void delContact(String fName, String lName) {
        this.contacts.delContact(new Contact(fName, lName));

    }

    @Override
    public void modifyContact(String fNameSource, String lNameSource,
            String fName, String lName, String hAddress, String cAddress,
            List<String> pPhones, List<String> cPhones, String homePage,
            List<String> emails, String photo, Map<String, String> others,
            List<String> groups) {
        Contact sContact = findContactByName(fNameSource, lNameSource);
        this.contacts.modifyContact(sContact, new Contact(fName, lName,
                hAddress, cAddress, pPhones, cPhones, homePage, emails, photo,
                others, groups, sContact.getInsertDate()));

    }

    @Override
    public Boolean existsContactByName(String fName, String lName) {
        if (this.contacts.getContact(fName, lName) != null) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public Contact findContactByName(String fName, String lName) {

        return this.contacts.getContact(fName, lName);
    }

    @Override
    public Map<String, Contact> getAllContacts() {
        return this.contacts.getAllContacts();
    }

    @Override
    public void importFile(FileWindow fileWindow, String absolutePath) {
        long startTime = System.currentTimeMillis();
        List<String> pPhones = new ArrayList<>();
        List<String> cPhones = new ArrayList<>();
        List<String> emails = new ArrayList<>();
        Map<String, String> others = new HashMap<>();
        List<String> groups = new ArrayList<>();
        String fName = "";
        String lName = "";
        String hAddress = "";
        String cAddress = "";
        String homePage = "";
        String photo = "";
        Date insertDate = new Date();

        try (BufferedReader br = new BufferedReader(new FileReader(absolutePath))) {
            LineNumberReader lnr = new LineNumberReader(new FileReader(absolutePath));
            lnr.skip(Long.MAX_VALUE);
            int numberLines = lnr.getLineNumber();
            String line = br.readLine();
            while (line != null) {
                fName = "";
                lName = "";
                hAddress = "";
                cAddress = "";
                pPhones = new ArrayList<>();
                cPhones = new ArrayList<>();
                homePage = "";
                emails = new ArrayList<>();
                photo = "";
                others = new HashMap<>();
                groups = new ArrayList<>();
                insertDate = new Date();

                String[] values = line.split(", ");

                for (int i = 0; i < values.length; i++) {

                    if (i == 0 && !"".equals(values[i])) {
                        fName = values[i];
                    } else if (i == 1 && !"".equals(values[i])) {
                        lName = values[i];
                    } else if (i == 2 && !"".equals(values[i])) {
                        hAddress = values[i];
                    } else if (i == 3 && !"".equals(values[i])) {
                        cAddress = values[i];
                    } else if (i == 4 && !"[]".equals(values[i])) {
                        String value = values[i].replace("[", "");
                        value = value.replace("]", "");
                        String[] split = value.split("; ");
                        for (int j = 0; j < split.length; j++) {
                            pPhones.add(split[j]);
                        }
                    } else if (i == 5 && !"[]".equals(values[i])) {
                        String value = values[i].replace("[", "");
                        value = value.replace("]", "");
                        String[] split = value.split("; ");
                        for (int j = 0; j < split.length; j++) {
                            cPhones.add(split[j]);
                        }
                    } else if (i == 6 && !"".equals(values[i])) {
                        homePage = values[i];
                    } else if (i == 7 && !"[]".equals(values[i])) {
                        String value = values[i].replace("[", "");
                        value = value.replace("]", "");
                        String[] split = value.split("; ");
                        for (int j = 0; j < split.length; j++) {
                            emails.add(split[j]);
                        }
                    } else if (i == 8 && !"".equals(values[i])) {
                        photo = values[i];
                    } else if (i == 9 && !"{}".equals(values[i])) {
                        //{mq=sfeu; yr=qlsxeh; aw=lhql}
                        values[i] = values[i].replace("{", "");
                        values[i] = values[i].replace("}", "");
                        for (String pairRaw : values[i].split("; ")) {
                            String pair[] = pairRaw.split("=");
                            others.put(pair[0], pair[1]);
                        }

                    } else if (i == 10 && !"[]".equals(values[i])) {
                        String value = values[i].replace("[", "");
                        value = value.replace("]", "");
                        String[] split = value.split("; ");
                        for (int j = 0; j < split.length; j++) {
                            groups.add(split[j]);
                        }
                    } else if (i == 11) {
                        insertDate = new Date();
                        insertDate.setTime(Long.parseLong(values[i]));
                    }
                }
                mainWindow.addRow(new Contact(fName, lName, hAddress, cAddress, pPhones, cPhones, homePage, emails, photo, others, groups, insertDate));

                line = br.readLine();

                try {
                    Thread.sleep(SLEEPFORDEBUG);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
                }

            }

        } catch (FileNotFoundException ex) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
        }

        long endTime = System.currentTimeMillis();
        System.out.println("IMPORT DONE IN " + (endTime - startTime) + " MILLISECONDS "+absolutePath);
    }

    @Override
    public void exportFile(FileWindow fileWindow, String absolutePath) {
        long startTime = System.currentTimeMillis();
        Map<String, Contact> contactsMap = contacts.getAllContacts();
        PrintWriter writer;
        try {
            writer = new PrintWriter(absolutePath, "UTF-8");

            for (Map.Entry<String, Contact> entry : contactsMap.entrySet()) {

                writer.println(entry.getValue().toStringCSV());
                try {
                    Thread.sleep(SLEEPFORDEBUG);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            writer.close();
            long endTime = System.currentTimeMillis();
            System.out.println("EXPORT DONE IN " + (endTime - startTime) + "MILLISECONDS " +absolutePath);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

}
